﻿//NGit is derived from jgit (http://eclipse.org/jgit).
//Copyright owners are documented in jgit's IP log.

//This program and the accompanying materials are made available
//under the terms of the Eclipse Distribution License v1.0 which
//accompanies this distribution, is reproduced below, and is
//available at http://www.eclipse.org/org/documents/edl-v10.php

//All rights reserved.

//Redistribution and use in source and binary forms, with or
//without modification, are permitted provided that the following
//conditions are met:

//- Redistributions of source code must retain the above copyright
//  notice, this list of conditions and the following disclaimer.

//- Redistributions in binary form must reproduce the above
//  copyright notice, this list of conditions and the following
//  disclaimer in the documentation and/or other materials provided
//  with the distribution.

//- Neither the name of the Eclipse Foundation, Inc. nor the
//  names of its contributors may be used to endorse or promote
//  products derived from this software without specific prior
//  written permission.

//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
//CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
//STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


//*************************************************************************
//**  Included in JDMB 1.0 port to SharpDBM;  11/2013 Cyrus Neah cneah@codingreal.com
//**  SharpDBM is an independent reimplementation of the JDBM 1.0 software library in C#  
//*************************************************************************

namespace SharpDBM.helper
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Collections;
    using SharpDBM.recman;

    public class TreeSet<T> : AbstractSet<T>
    {
        private SortedDictionary<T, int> dict;
        private BlockIoComparator comparator = new BlockIoComparator();

        public TreeSet()
        {
            this.dict = new SortedDictionary<T, int>();
        }

        
        public TreeSet(IEnumerable<T> items)
        {
            this.dict = new SortedDictionary<T, int>();
            foreach (var i in items)
                AddItem(i);
        }

        public override bool AddItem(T element)
        {
            if (!this.dict.ContainsKey(element))
            {
                this.dict[element] = 0;
                return true;
            }
            return false;
        }

        public override void Clear()
        {
            this.dict.Clear();
        }

        public int Compare(T a, T b)
        {
            //return Comparer<T>.Default.Compare(a, b);
            return comparator.Compare(a,b);
        }

        public override bool Contains(object item)
        {
            return this.dict.ContainsKey((T)item);
        }

        public T First()
        {
            if (this.dict.Count == 0)
            {
                throw new NoSuchMethodException();
            }
            return this.dict.Keys.First<T>();
        }

        public ICollection<T> HeadSet(T toElement)
        {
            List<T> list = new List<T>();
            foreach (T t in this)
            {
                if (this.Compare(t, toElement) >= 0)
                    return list;
                list.Add(t);
            }
            return list;
        }

        public override Iterator<T> Iterator()
        {
            return new EnumeratorWrapper<T>(this.dict.Keys, this.dict.Keys.GetEnumerator());
        }

        public override bool Remove(object element)
        {
            return this.dict.Remove((T)element);
        }

        public override int Count
        {
            get { return this.dict.Count; }
        }

        public override string ToString()
        {
            return "[" + string.Join(", ", this.Select(d => d.ToString()).ToArray()) + "]";
        }
    }

    public abstract class AbstractSet<T> : AbstractCollection<T>
    {
        protected AbstractSet()
        {
        }

        public override bool Equals(object obj)
        {
            if (obj == this)
                return true;
            ICollection<T> c = obj as ICollection<T>;
            if (c != null)
            {
                if (c.Count != Count)
                    return false;
                return ContainsAll(c);
            }
            ICollection<object> co = obj as ICollection<object>;
            if (co != null)
            {
                if (co.Count != Count)
                    return false;
                return ContainsAll(co);
            }
            return false;
        }

        public override int GetHashCode()
        {
            int t = 0;
            foreach (object o in this)
                if (o != null)
                    t += o.GetHashCode();
            return t;
        }
    }

    public abstract class AbstractCollection<T> : Iterable<T>, IEnumerable, ICollection<T>, IEnumerable<T>
    {
        protected AbstractCollection()
        {
        }

        public virtual bool AddItem(T element)
        {
            throw new NotSupportedException();
        }

        public virtual void Clear()
        {
            Iterator iterator = Iterator();
            while (iterator.HasNext())
            {
                iterator.Next();
                iterator.Remove();
            }
        }

        public virtual bool Contains(object item)
        {
            foreach (var t in this)
            {
                if (object.ReferenceEquals(t, item) || t.Equals(item))
                    return true;
            }
            return false;
        }

        public virtual bool ContainsAll(ICollection<object> c)
        {
            foreach (var t in c)
            {
                if (!Contains(t))
                    return false;
            }
            return true;
        }

        public bool ContainsAll(ICollection<T> c)
        {
            List<object> list = new List<object>(c.Count);
            foreach (var t in c)
                list.Add(t);
            return ContainsAll((ICollection<object>)list);
        }

        public virtual bool IsEmpty()
        {
            return (this.Count == 0);
        }

        public virtual bool Remove(object element)
        {
            Iterator iterator = Iterator();
            while (iterator.HasNext())
            {
                if (iterator.Next().Equals(element))
                {
                    iterator.Remove();
                    return true;
                }
            }
            return false;
        }

        void ICollection<T>.Add(T element)
        {
            AddItem(element);
        }

        bool ICollection<T>.Contains(T item)
        {
            return Contains(item);
        }

        void ICollection<T>.CopyTo(T[] array, int arrayIndex)
        {
            foreach (T t in this)
                array[arrayIndex++] = t;
        }

        bool ICollection<T>.Remove(T item)
        {
            return Remove(item);
        }

        public abstract int Count { get; }

        bool ICollection<T>.IsReadOnly
        {
            get { return false; }
        }
    }

    public interface Iterator
    {
        bool HasNext();
        object Next();
        void Remove();
    }

    public abstract class Iterator<T> : IEnumerator, IDisposable, IEnumerator<T>, Iterator
    {
        private T lastValue;

        protected Iterator()
        {
        }

        object Iterator.Next()
        {
            return Next();
        }

        public abstract bool HasNext();
        public abstract T Next();
        public abstract void Remove();

        bool IEnumerator.MoveNext()
        {
            if (HasNext())
            {
                lastValue = Next();
                return true;
            }
            return false;
        }

        void IEnumerator.Reset()
        {
            throw new NotImplementedException();
        }

        void IDisposable.Dispose()
        {
        }

        T IEnumerator<T>.Current
        {
            get { return lastValue; }
        }

        object IEnumerator.Current
        {
            get { return lastValue; }
        }
    }
    public abstract class Iterable<T> : IEnumerable, IEnumerable<T>
    {
        protected Iterable()
        {
        }

        public IEnumerator<T> GetEnumerator()
        {
            return this.Iterator();
        }

        public abstract Iterator<T> Iterator();

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.Iterator();
        }
    }

    internal class EnumerableWrapper<T> : Iterable<T>
    {
        private IEnumerable<T> e;

        public EnumerableWrapper(IEnumerable<T> e)
        {
            this.e = e;
        }

        public override Iterator<T> Iterator()
        {
            return new EnumeratorWrapper<T>(this.e, this.e.GetEnumerator());
        }
    }

    internal class EnumeratorWrapper<T> : Iterator<T>
    {
        object collection;
        IEnumerator<T> e;
        T lastVal;
        bool more;
        bool copied;

        public EnumeratorWrapper(object collection, IEnumerator<T> e)
        {
            this.e = e;
            this.collection = collection;
            this.more = e.MoveNext();
        }

        public override bool HasNext()
        {
            return this.more;
        }

        public override T Next()
        {
            if (!more)
                throw new NoSuchElementException();
            lastVal = e.Current;
            more = e.MoveNext();
            return lastVal;
        }

        public override void Remove()
        {
            ICollection<T> col = this.collection as ICollection<T>;
            if (col == null)
            {
                throw new NotSupportedException();
            }
            if (more && !copied)
            {
                // Read the remaining elements, since the current enumerator
                // will be invalid after removing the element
                List<T> remaining = new List<T>();
                do
                {
                    remaining.Add(e.Current);
                } while (e.MoveNext());
                e = remaining.GetEnumerator();
                e.MoveNext();
                copied = true;
            }
            col.Remove(lastVal);
        }
    }
    public class VirtualMachineError : Error
    {
    }

    public class StackOverflowError : VirtualMachineError
    {
        public StackOverflowError()
        {
        }
    }

    public class BrokenBarrierException : Exception
    {
    }

    internal class BufferUnderflowException : Exception
    {
    }

    public class CharacterCodingException : Exception
    {
    }

    public class DataFormatException : Exception
    {
    }

    public class EOFException : Exception
    {
        public EOFException()
        {
        }

        public EOFException(string msg)
            : base(msg)
        {
        }
    }

    public class Error : Exception
    {
        public Error()
        {
        }

        public Error(Exception ex)
            : base("Runtime Exception", ex)
        {
        }

        public Error(string msg)
            : base(msg)
        {
        }

        public Error(string msg, Exception ex)
            : base(msg, ex)
        {
        }
    }

    public class ExecutionException : Exception
    {
        public ExecutionException(Exception inner)
            : base("Execution failed", inner)
        {
        }
    }

    public class InstantiationException : Exception
    {
    }

    public class InterruptedIOException : Exception
    {
        public InterruptedIOException(string msg)
            : base(msg)
        {
        }
    }

    public class MissingResourceException : Exception
    {
    }

    public class NoSuchAlgorithmException : Exception
    {
    }

    public class NoSuchElementException : Exception
    {
    }

    internal class NoSuchMethodException : Exception
    {
    }

    internal class OverlappingFileLockException : Exception
    {
    }

    public class ParseException : Exception
    {
        public ParseException()
        {
        }

        public ParseException(string msg, int errorOffset)
            : base(string.Format("Msg: msg. Error Offset: {1}", msg, errorOffset))
        {
        }
    }

    public class RuntimeException : Exception
    {
        public RuntimeException()
        {
        }

        public RuntimeException(Exception ex)
            : base("Runtime Exception", ex)
        {
        }

        public RuntimeException(string msg)
            : base(msg)
        {
        }

        public RuntimeException(string msg, Exception ex)
            : base(msg, ex)
        {
        }
    }

    internal class StringIndexOutOfBoundsException : Exception
    {
    }

    internal class UnknownHostException : Exception
    {
    }

    internal class UnsupportedEncodingException : Exception
    {
    }

    internal class URISyntaxException : Exception
    {
        public URISyntaxException(string s, string msg)
            : base(s + " " + msg)
        {
        }
    }

    internal class ZipException : Exception
    {
    }

    public class GitException : Exception
    {
    }

    class ConnectException : Exception
    {
        public ConnectException(string msg)
            : base(msg)
        {
        }
    }

    class KeyManagementException : Exception
    {
    }

    class IllegalCharsetNameException : Exception
    {
        public IllegalCharsetNameException(string msg)
            : base(msg)
        {
        }
    }

    class UnsupportedCharsetException : Exception
    {
        public UnsupportedCharsetException(string msg)
            : base(msg)
        {
        }
    }
}
